/*
 * @Author: xiaosihan
 * @Date: 2021-04-18 10:08:38
 * @Last Modified by: xiaosihan
 * @Last Modified time: 2022-06-08 14:33:33
 */

import _ from "lodash";
import Mesh, { MeshProps } from "../Mesh/Mesh";
import fontContorller from "./fontController";
import * as THREE from "three";
import { TextGeometry } from 'three/examples/jsm/geometries/TextGeometry.js';

export interface Text3DProps extends MeshProps {

    // 字体
    fontFamily?: "simhei" | "simkei",
    text?: string;
    size?: number;
    curveSegments?: number; // 曲线段的密度
    textAlign?: "left_bottom" | "left_center" | "left_top" | "center_bottom" | "center_center" | "center_top" | "right_bottom" | "right_center" | "right_top"
    height?: number, // 文字的厚度
    bevelThickness?: number, // 斜角厚度
    bevelSize?: number, // 斜角大小
    bevelEnabled?: boolean, // 斜角开启
    bevelOffset?: number,// 斜角偏移
    bevelSegments?: number//斜角分段

    update?: (renderer: THREE.WebGLRenderer, scene: THREE.Scene, camera: THREE.Camera, object3d: THREE.Object3D) => void; // 当文字加载过程中更新回调
}

export default class Text3D extends Mesh<Text3DProps> {
    constructor(props: Text3DProps) {
        super(props);
    }

    setGeometry() {

        const {
            fontFamily = "simhei",
            text = "<Text3D/>",
            size = 5,
            curveSegments = 1,
            textAlign = "left_bottom",
            height = 0.4, // 文字的厚度
            bevelEnabled = true, // 斜角开启
            bevelThickness = 0.2, // 斜角厚度
            bevelSize = 0.15, // 斜角大小
            bevelOffset = 0,// 斜角偏移
            bevelSegments = 1,//斜角分段
            update
        } = this.props;

        const { renderer, scene, camera } = this.context;
        const { geometry, material } = this.object3d;

        // 参数都没有变时 无需重复创建 文字模型
        if (_.isEqual({
            fontFamily,
            text,
            size,
            curveSegments,
            textAlign,
            height,
            bevelThickness,
            bevelSize,
            bevelEnabled,
            bevelOffset,
            bevelSegments
        }, this.object3d.geometry.userData)) {
            return;
        }

        fontContorller.loadText({
            fontType: fontFamily,
            text: text,
            callback: THREEFont => {

                let Text3DGeometry = new TextGeometry(text, {
                    font: THREEFont,
                    size,
                    height,
                    curveSegments,
                    bevelEnabled,
                    bevelThickness,
                    bevelSize,
                    bevelOffset,
                    bevelSegments
                });

                Text3DGeometry.userData = {
                    fontFamily,
                    text,
                    size,
                    height,
                    curveSegments,
                    textAlign,
                    bevelEnabled,
                    bevelThickness,
                    bevelSize,
                    bevelOffset,
                    bevelSegments,
                }

                // 计算文字的位置
                Text3DGeometry.computeBoundingBox();

                if (Text3DGeometry.boundingBox) {

                    let { max, min } = Text3DGeometry.boundingBox;

                    let width = max.x - min.x;
                    let hieght = max.y - min.y;
                    let thickness = max.z - min.z;

                    if (["center_bottom", "center_center", "center_top"].includes(textAlign)) {
                        Text3DGeometry.translate((width / -2) - min.x, 0, 0);
                    }

                    if (["right_bottom", "right_center", "right_top"].includes(textAlign)) {
                        Text3DGeometry.translate((width / -1) - min.x, 0, 0);
                    }

                    if (["left_center", "center_center", "right_center"].includes(textAlign)) {
                        Text3DGeometry.translate(0, (hieght / - 2) - min.y, 0);
                    }

                    if (["left_top", "center_top", "right_top"].includes(textAlign)) {
                        Text3DGeometry.translate(0, (hieght / - 1) - min.y, 0);
                    }

                    Text3DGeometry.translate(bevelOffset - bevelOffset, bevelOffset - bevelOffset, (thickness / -2) - min.z);
                }

                this.object3d.geometry.dispose();
                this.object3d.geometry = Text3DGeometry;

                update && update(renderer, scene, camera, this.object3d as unknown as THREE.Object3D);

            }
        });

    }

    componentWillUnmount() {
        this.object3d.geometry.dispose();
    }

    render() {
        return null;
    }

}